package com.springboot.demo.common.utils;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * @ClassName:QRCodeUtil.java
 * @Package com.Utils
 * @Description:制作二维码
 * @Author JuoChiu
 * @Date  2017年11月28日下午2:30:35
 * @Version
 */
@SuppressWarnings("all")
public class QRCodeUtil {
	private static final int BLACK = 0xFF000000;//用于设置图案的颜色  
    private static final int WHITE = 0xFFFFFFFF; //用于背景色  
  
    private QRCodeUtil() {  
    }  
  
    public static BufferedImage toBufferedImage(BitMatrix matrix) {  
        int width = matrix.getWidth();  
        int height = matrix.getHeight();  
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
        for (int x = 0; x < width; x++) {  
            for (int y = 0; y < height; y++) {  
                image.setRGB(x, y,  (matrix.get(x, y) ? BLACK : WHITE));  
                //image.setRGB(x, y,  (matrix.get(x, y) ? Color.YELLOW.getRGB() : Color.CYAN.getRGB()));  
            }  
        }  
        return image;  
    }  
  
    public static String writeToFile(BitMatrix matrix, String format, File file) throws IOException {  
        BufferedImage image = toBufferedImage(matrix);  
        //设置logo图标 
        image = LogoMatrix(image);
          
        if (!ImageIO.write(image, format, file)) {  
            throw new IOException("Could not write an image of format " + format + " to " + file);  
        }else{
        	System.out.println("图片生成成功！");
        	return "图片生成成功！";
        }  
    }
  
    public static void writeToStream(BitMatrix matrix, String format, OutputStream stream) throws IOException {  
        BufferedImage image = toBufferedImage(matrix);  
        //设置logo图标  
        image = LogoMatrix(image);
        
        if (!ImageIO.write(image, format, stream)) {  
            throw new IOException("Could not write an image of format " + format);  
        }  
    }
    
    /**
     * @MethodName:LogoMatrix
     * @Author JuoChiu
     * @Date 2017年11月28日 下午2:31:56
     * @Description:二维码 添加 logo图标 处理的方法,模仿微信自动生成二维码效果，有圆角边框，logo和二维码间有空白区，logo带有灰色边框
     * @param matrixImage 源二维码图片 
     * @return 返回带有logo的二维码图片 
     * @throws IOException
     * @ReturnType BufferedImage
     */
    public static BufferedImage LogoMatrix(BufferedImage matrixImage) throws IOException{  
        // 读取二维码图片，并构建绘图对象 
        Graphics2D g2 = matrixImage.createGraphics();  
          
        int matrixWidth = matrixImage.getWidth();  
        int matrixHeigh = matrixImage.getHeight();  
          
        // 读取Logo图片   
        BufferedImage logo = ImageIO.read(new File("D:\\logo1.jpg"));  
 
        //开始绘制图片  
        g2.drawImage(logo,matrixWidth/5*2,matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5, null);//绘制       
        BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);   
        g2.setStroke(stroke);// 设置笔画对象  
        
        //指定弧度的圆角矩形  
        RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth/5*2, matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5,20,20);  
        g2.setColor(Color.white);  
        g2.draw(round);// 绘制圆弧矩形  
          
        //设置logo 有一道灰色边框  
        BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);   
        g2.setStroke(stroke2);// 设置笔画对象  
        RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth/5*2+2, matrixHeigh/5*2+2, matrixWidth/5-4, matrixHeigh/5-4,20,20);  
        g2.setColor(new Color(128,128,128));  
        g2.draw(round2);// 绘制圆弧矩形  
          
        g2.dispose();  
        matrixImage.flush() ;  
        return matrixImage ;  
    }
    
    /**
     * @MethodName:Encode_QR_CODE
     * @Author JuoChiu
     * @Date 2017年11月28日 下午2:42:42
     * @Description:二维码的大小设置
     * @throws IOException
     * @throws WriterException
     * @ReturnType void
     */
    public static void Encode_QR_CODE() throws IOException, WriterException{  
        String contents = "忍不住了吧，扫了吧！哇哈哈"; // 二维码内容  
        int width = 430; // 二维码图片宽度 300   
        int height = 430; // 二维码图片高度300  
          
        String format = "jpg";// 二维码的图片格式 jpg  
          
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();  
         // 指定纠错等级,纠错级别（L 7%、M 15%、Q 25%、H 30%）  
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);  
        // 内容所使用字符集编码  
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");     
        //hints.put(EncodeHintType.MAX_SIZE, 350);//设置图片的最大值  
        //hints.put(EncodeHintType.MIN_SIZE, 100);//设置图片的最小值  
        hints.put(EncodeHintType.MARGIN, 1);//设置二维码边的空度，非负数  
          
        BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,//要编码的内容  
                //编码类型，目前zxing支持：Aztec 2D,CODABAR 1D format,Code 39 1D,Code 93 1D ,Code 128 1D,  
                //Data Matrix 2D , EAN-8 1D,EAN-13 1D,ITF (Interleaved Two of Five) 1D,  
                //MaxiCode 2D barcode,PDF417,QR Code 2D,RSS 14,RSS EXPANDED,UPC-A 1D,UPC-E 1D,UPC/EAN extension,UPC_EAN_EXTENSION  
                BarcodeFormat.QR_CODE,  
                width, //条形码的宽度  
                height, //条形码的高度  
                hints);//生成条形码时的一些配置,此项可选  
          
        // 生成二维码  
        File outputFile = new File("d:" + File.separator + "new-3.jpg");//指定输出路径  
          
        writeToFile(bitMatrix, format, outputFile);  
    }
    
    public static void main(String[] args) throws Exception {  
        try {  
            Encode_QR_CODE();  
        } catch (Exception e) {  
            // TODO: handle exception  
            e.printStackTrace();  
        }  
    }
}
